package com.dashu.school.service;


import com.dashu.base.enums.ReplRyCode;
import com.dashu.base.enums.common.SubordinateType;
import com.dashu.base.enums.common.UserType;
import com.dashu.base.enums.common.functionAM.*;
import com.dashu.base.utils.CopyUtil;
import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.base.utils.http.token.TokenTools;
import com.dashu.school.dto.*;
import com.dashu.school.handler.VerificationException;
import com.dashu.school.model.QUser;
import com.dashu.school.model.User;
import com.dashu.school.result.PageEnty;
import com.dashu.school.vo.UpdateEntityVO;
import com.dashu.school.vo.user.UserPassVo;
import com.dashu.school.vo.user.UserSubordinateVo;
import com.dashu.school.vo.user.UserVo;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.Arrays;
import java.util.List;


@Service
public class UserService extends DataService {

//    @Autowired
//    private OperatorService operatorService;
//    @Autowired
//    private PermissionService permissionService;

    public List<User> selec() {
        QUser quser = QUser.user;
        return queryFactory
                .select(quser)
                .from(quser)
                .fetch();
    }

    public UserLoginDTO login(String userName, String password) {
        QUser quser = QUser.user;
        UserLoginDTO userLoginDTO = new UserLoginDTO();
        DozerBeanMapper mapper = new DozerBeanMapper();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(quser.userName.eq(userName));
        booleanBuilder.and(quser.userPass.eq(password));
        User user = queryFactory
                .select(quser)
                .from(quser)
                .where(booleanBuilder.getValue()).fetchOne();
        if (user == null) return null;
        if (SubordinateType.DISABLE.equals(user.getSubordinate()))
            throw new VerificationException(ReplRyCode.DISABLE, ReplRyCode.DISABLE.getMessage());
        String token = TokenTools.createToken(VerificationUtil.getRequest(), user.getUserName(), String.valueOf(user.getId()));
        UserDTO userDTO = mapper.map(user, UserDTO.class);
        userDTO.setToken(token);
//        PermissionDTO permissionDTO = permissionService.findByPermissionRuleId(user.getPid());
//        PermissionLoginDTO permissionLoginDTO = new PermissionLoginDTO();
//        permissionLoginDTO.setBaseId(permissionDTO.getBaseId());
//        permissionLoginDTO.setRuleName(permissionDTO.getRuleName());
//        permissionLoginDTO.setRuleType(permissionDTO.getRuleType());
//        if (permissionDTO.getBaseId() == 0) {
//            Arrays.asList(AttendanceAM.values()).stream().forEach(pa -> {
//                permissionOn(permissionLoginDTO, "pa", pa.name());
//            });
//            Arrays.asList(DeviceAM.values()).stream().forEach(pd -> {
//                permissionOn(permissionLoginDTO, "pd", pd.name());
//            });
//            Arrays.asList(PersonnelAM.values()).stream().forEach(pp -> {
//                permissionOn(permissionLoginDTO, "pp", pp.name());
//            });
//            Arrays.asList(RootAm.values()).stream().forEach(pr -> {
//                permissionOn(permissionLoginDTO, "pr", pr.name());
//            });
//            Arrays.asList(SystemAM.values()).stream().forEach(ps -> {
//                permissionOn(permissionLoginDTO, "ps", ps.name());
//            });
//            Arrays.asList(TeachingAM.values()).stream().forEach(pt -> {
//                permissionOn(permissionLoginDTO, "pt", pt.name());
//            });
//        } else {
//            Arrays.asList(permissionDTO.getRuleAttendance().split(",")).stream().forEach(pa -> {
//                permissionOn(permissionLoginDTO, "pa", pa);
//            });
//            Arrays.asList(permissionDTO.getRuleDevice().split(",")).stream().forEach(pd -> {
//                permissionOn(permissionLoginDTO, "pd", pd);
//            });
//            Arrays.asList(permissionDTO.getRulePersonnel().split(",")).stream().forEach(pp -> {
//                permissionOn(permissionLoginDTO, "pp", pp);
//            });
//            Arrays.asList(permissionDTO.getRuleRoot().split(",")).stream().forEach(pr -> {
//                permissionOn(permissionLoginDTO, "pr", pr);
//            });
//            Arrays.asList(permissionDTO.getRuleSystem().split(",")).stream().forEach(ps -> {
//                permissionOn(permissionLoginDTO, "ps", ps);
//            });
//            Arrays.asList(permissionDTO.getRuleTeaching().split(",")).stream().forEach(pt -> {
//                permissionOn(permissionLoginDTO, "pt", pt);
//            });
//
//        }
        userLoginDTO.setUserData(userDTO);
//        userLoginDTO.setPermissionLoginDTO(permissionLoginDTO);
        return userLoginDTO;
    }


    @Transactional
    public UserDTO add(UserVo userVO) throws Exception {
        User user = CopyUtil.copyEnty(userVO, User.class);
        long baseId = userVO.getBaseId() == 0 ? Long.parseLong(VerificationUtil.getUserId()) : userVO.getBaseId();
        UserDTO baseUserDTO = findByUserId(baseId);
        if (baseUserDTO.getLevel() > 2)
            throw new VerificationException(ReplRyCode.LEVEL_ERROR, ReplRyCode.LEVEL_ERROR.getMessage());
        user.setId(UIDUtil.nextId());
        user.setCreateUser(baseId);
        user.setCreateTime(System.currentTimeMillis());
        user.setUserName(userVO.getUserName());
        user.setUserPass(userVO.getUserPass());
        user.setUserType(UserType.map.get(userVO.getUserType()));
        user.setSubordinate(SubordinateType.map.get(userVO.getSubordinate()));
        user.setNickname(userVO.getNickname());
        user.setBaseId(userVO.getBaseId());
        user.setPid(userVO.getRuleId());
        user.setLevel(baseUserDTO.getLevel() + 1);
        entityManager.persist(user);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        UserDTO userDTO = CopyUtil.copyEnty(user, UserDTO.class);
        return userDTO;

    }

    @Transactional
    public boolean deleteByUserId(long userId) {
        QUser qUser = QUser.user;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qUser.id.eq(userId));
        User user;
        queryFactory.select();
        user = queryFactory
                .select(qUser)
                .from(qUser)
                .where(booleanBuilder.getValue()).fetchOne();
        if (user == null)
            throw new VerificationException(ReplRyCode.USER_NOT_DATA, ReplRyCode.USER_NOT_DATA.getMessage());
        entityManager.remove(user);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);
        return true;

    }


    @Transactional
    public boolean existByPermissionRuleId(long ruleId) {
        QUser qUser = QUser.user;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qUser.pid.eq(ruleId));
        List<User> users = queryFactory
                .select(qUser)
                .from(qUser)
                .where(booleanBuilder.getValue()).fetch();
        if (users.size() > 0)
            return true;

        return false;
    }

    @Transactional
    public boolean updataUser(UpdateEntityVO<UserPassVo> updataUserVo) throws Exception {
        QUser quser = QUser.user;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        UserPassVo userPassVo = updataUserVo.getEntityVO();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(quser.id.eq(updataUserVo.getId()));
        User user = queryFactory
                .select(quser)
                .from(quser)
                .where(booleanBuilder.getValue()).fetchFirst();
        if (user == null)
            throw new VerificationException(ReplRyCode.USER_NOT_DATA, ReplRyCode.USER_NOT_DATA.getMessage());
        if (userPassVo.getOriginalPass() == null)
            throw new VerificationException(ReplRyCode.USER_ORIGINAL_NULL, ReplRyCode.USER_ORIGINAL_NULL.getMessage());
        if (!userPassVo.getOriginalPass().equals(user.getUserPass()))
            throw new VerificationException(ReplRyCode.USER_ORIGINAL_PASS, ReplRyCode.USER_ORIGINAL_PASS.getMessage());
        user.setUpdateTime(System.currentTimeMillis());
        user.setUpdateUser(userId);
        if (userPassVo.getUserPass() != null)
            user.setUserPass(userPassVo.getUserPass());
        entityManager.merge(user);
        return true;
    }

    @Transactional
    public boolean updataSubordinate(UpdateEntityVO<UserSubordinateVo> updataUserVo) throws Exception {
        QUser quser = QUser.user;
        long userId = Long.parseLong(VerificationUtil.getUserId());
        UserSubordinateVo userSubordinateVo = updataUserVo.getEntityVO();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(quser.id.eq(updataUserVo.getId()));
        User user = queryFactory
                .select(quser)
                .from(quser)
                .where(booleanBuilder.getValue()).fetchFirst();
        if (user == null)
            throw new VerificationException(ReplRyCode.USER_NOT_DATA, ReplRyCode.USER_NOT_DATA.getMessage());
        user.setSubordinate(SubordinateType.map.get(userSubordinateVo.getSubordinate()));
        user.setUpdateTime(System.currentTimeMillis());
        user.setUpdateUser(userId);
        entityManager.merge(user);
        return true;
    }


    public List<UserDTO> findByCreteUser(PageEnty<Long> createUser) throws Exception {
        QUser qUser = QUser.user;
        List<UserDTO> userDTOS = Lists.newArrayList();
        long baseId = createUser.getBaseId() == 0 ? Long.parseLong(VerificationUtil.getUserId()) : createUser.getBaseId();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qUser.createUser.eq(baseId));
        List<User> users = queryFactory
                .select(qUser)
                .from(qUser)
                .where(booleanBuilder.getValue())
                .offset((createUser.getPage() - 1) * createUser.getNum())
                .limit(createUser.getNum())
                .fetch();
        users.stream().forEach(u -> {
            UserDTO userDTO = CopyUtil.copyEnty(u, UserDTO.class);
//            PermissionDTO permissionDTO = permissionService.findByPermissionRuleId(u.getPid());
//            userDTO.setPermissison(permissionDTO.getRuleName());
            userDTOS.add(userDTO);
        });
        return userDTOS;

    }

    public UserDTO findByUserId(long UserId) {
        QUser qUser = QUser.user;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qUser.id.eq(UserId));
        User user = queryFactory
                .select(qUser)
                .from(qUser)
                .where(booleanBuilder.getValue()).fetchOne();
        if (user == null)
            throw new VerificationException(ReplRyCode.USER_NOT_DATA, ReplRyCode.USER_NOT_DATA.getMessage());
        UserDTO userDTO = CopyUtil.copyEnty(user, UserDTO.class);
        return userDTO;

    }

    public UserDTO existByUserName(String UserName) {
        QUser qUser = QUser.user;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qUser.userName.eq(UserName));
        User user = queryFactory
                .select(qUser)
                .from(qUser)
                .where(booleanBuilder.getValue()).fetchOne();
        UserDTO userDTO = CopyUtil.copyEnty(user, UserDTO.class);
        return userDTO;

    }

    public void permissionOn(PermissionLoginDTO permissionLoginDTO, String type, String data) {
        PermissionInfoDTO permissionInfoDTO = new PermissionInfoDTO();
        if (!StringUtils.isEmpty(data)) {
            switch (type) {
                case "pa":
                    AttendanceAM attendanceAM = AttendanceAM.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(attendanceAM.name);
                    permissionInfoDTO.setUrl(attendanceAM.url);
                    permissionInfoDTO.setPath(attendanceAM.path);
                    permissionInfoDTO.setIcon(attendanceAM.icon);
                    permissionLoginDTO.getRuleAttendances().add(permissionInfoDTO);
                    break;
                case "pd":
                    DeviceAM deviceAM = DeviceAM.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(deviceAM.name);
                    permissionInfoDTO.setUrl(deviceAM.url);
                    permissionInfoDTO.setPath(deviceAM.path);
                    permissionInfoDTO.setIcon(deviceAM.icon);
                    permissionLoginDTO.getRuleDevices().add(permissionInfoDTO);
                    break;
                case "pp":
                    PersonnelAM personnelAM = PersonnelAM.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(personnelAM.name);
                    permissionInfoDTO.setUrl(personnelAM.url);
                    permissionInfoDTO.setPath(personnelAM.path);
                    permissionInfoDTO.setIcon(personnelAM.icon);
                    permissionLoginDTO.getRulePersonnels().add(permissionInfoDTO);
                    break;
                case "pr":
                    RootAm rootAm = RootAm.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(rootAm.name);
                    permissionInfoDTO.setUrl(rootAm.url);
                    permissionInfoDTO.setPath(rootAm.path);
                    permissionInfoDTO.setIcon(rootAm.icon);
                    permissionLoginDTO.getRuleRoots().add(permissionInfoDTO);
                    break;
                case "ps":
                    SystemAM systemAM = SystemAM.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(systemAM.name);
                    permissionInfoDTO.setUrl(systemAM.url);
                    permissionInfoDTO.setPath(systemAM.path);
                    permissionInfoDTO.setIcon(systemAM.icon);
                    permissionLoginDTO.getRuleSystems().add(permissionInfoDTO);
                    break;
                case "pt":
                    TeachingAM teachingAM = TeachingAM.map.get(data);
                    permissionInfoDTO.setCode(data);
                    permissionInfoDTO.setName(teachingAM.name);
                    permissionInfoDTO.setUrl(teachingAM.url);
                    permissionInfoDTO.setPath(teachingAM.path);
                    permissionInfoDTO.setIcon(teachingAM.icon);
                    permissionLoginDTO.getRuleTeachings().add(permissionInfoDTO);
                    break;
            }

        }
    }


}
